import os
import traceback
from datetime import datetime

from biz.entity.review_entity import MergeRequestReviewEntity, PushReviewEntity
from biz.event.event_manager import event_manager
from biz.gitlab.webhook_handler import filter_changes, MergeRequestHandler, PushHandler
from biz.github.webhook_handler import filter_changes as filter_github_changes, PullRequestHandler as GithubPullRequestHandler, PushHandler as GithubPushHandler
from biz.utils.code_reviewer import CodeReviewer
from biz.utils.im import notifier
from biz.utils.log import logger



def handle_push_event(webhook_data: dict, gitlab_token: str, gitlab_url: str, gitlab_url_slug: str):
    push_review_enabled = os.environ.get('PUSH_REVIEW_ENABLED', '0') == '1'
    logger.info(f"🚀 开始处理Push事件 - Push Review启用状态: {push_review_enabled}")
    
    try:
        # 提取基本信息
        project_name = webhook_data.get('project', {}).get('name', 'Unknown')
        user_name = webhook_data.get('user_username', 'Unknown')
        ref = webhook_data.get('ref', 'Unknown')
        logger.info(f"📋 Push事件详情 - 项目: {project_name}, 用户: {user_name}, 分支: {ref}")
        
        handler = PushHandler(webhook_data, gitlab_token, gitlab_url)
        logger.info('📨 Push Hook事件已接收，开始处理')
        
        commits = handler.get_push_commits()
        if not commits:
            logger.error('❌ 获取提交信息失败')
            return
        
        logger.info(f"📝 获取到 {len(commits)} 个提交")
        for i, commit in enumerate(commits[:3]):  # 只显示前3个提交的信息
            logger.info(f"  提交 {i+1}: {commit.get('message', 'No message')[:50]}...")

        review_result = None
        score = 0
        if push_review_enabled:
            logger.info("🔍 开始获取代码变更")
            # 获取PUSH的changes
            changes = handler.get_push_changes()
            logger.info(f'📄 原始变更数量: {len(changes) if changes else 0}')
            
            changes = filter_changes(changes)
            logger.info(f'📄 过滤后变更数量: {len(changes) if changes else 0}')
            
            if not changes:
                logger.info('⚠️ 未检测到PUSH代码的修改,修改文件可能不满足SUPPORTED_EXTENSIONS。')
                review_result = "关注的文件没有修改"
            else:
                logger.info(f"✅ 检测到 {len(changes)} 个有效的代码变更")
                for change in changes[:3]:  # 只显示前3个变更的信息
                    logger.info(f"  变更文件: {change.get('new_path', 'Unknown')}")

            if len(changes) > 0:
                logger.info("🤖 开始AI代码审查")
                commits_text = ';'.join(commit.get('message', '').strip() for commit in commits)
                logger.info(f"📝 提交消息汇总: {commits_text[:100]}...")
                
                review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text)
                score = CodeReviewer.parse_review_score(review_text=review_result)
                logger.info(f"✅ AI审查完成，评分: {score}")
                
            # 将review结果提交到Gitlab的 notes
            logger.info("📤 准备将审查结果提交到GitLab")
            handler.add_push_notes(f'Auto Review Result: \n{review_result}')
            logger.info("✅ 审查结果已提交到GitLab")
        else:
            logger.info("⏭️ Push Review功能未启用，跳过代码审查")

        logger.info("💾 准备保存审查结果到数据库")
        event_manager['push_reviewed'].send(PushReviewEntity(
            project_name=webhook_data['project']['name'],
            author=webhook_data['user_username'],
            branch=webhook_data['project']['default_branch'],
            updated_at=int(datetime.now().timestamp()),  # 当前时间
            commits=commits,
            score=score,
            review_result=review_result,
            url_slug=gitlab_url_slug,
        ))
        logger.info("✅ Push事件处理完成，审查结果已保存")

    except Exception as e:
        error_message = f'Push事件处理出现未知错误: {str(e)}\n{traceback.format_exc()}'
        logger.error(f'❌ Push事件处理失败: {error_message}')
        notifier.send_notification(content=error_message)
        logger.error('🔔 错误通知已发送')


def handle_merge_request_event(webhook_data: dict, gitlab_token: str, gitlab_url: str, gitlab_url_slug: str):
    '''
    处理Merge Request Hook事件
    :param webhook_data:
    :param gitlab_token:
    :param gitlab_url:
    :param gitlab_url_slug:
    :return:
    '''
    logger.info("🔀 开始处理Merge Request事件")
    
    try:
        # 提取基本信息
        project_name = webhook_data.get('project', {}).get('name', 'Unknown')
        user_name = webhook_data.get('user', {}).get('username', 'Unknown')
        mr_attrs = webhook_data.get('object_attributes', {})
        mr_title = mr_attrs.get('title', 'Unknown')
        source_branch = mr_attrs.get('source_branch', 'Unknown')
        target_branch = mr_attrs.get('target_branch', 'Unknown')
        
        logger.info(f"📋 MR详情 - 项目: {project_name}, 作者: {user_name}")
        logger.info(f"📋 MR信息 - 标题: {mr_title}")
        logger.info(f"📋 分支信息 - 源分支: {source_branch} -> 目标分支: {target_branch}")
        
        # 解析Webhook数据
        handler = MergeRequestHandler(webhook_data, gitlab_token, gitlab_url)
        logger.info('📨 Merge Request Hook事件已接收，开始处理')

        logger.info(f"🔍 检查MR操作类型: {handler.action}")
        if handler.action not in ['open', 'update']:
            logger.info(f"⏭️ MR操作类型为 {handler.action}，跳过处理（仅处理 open/update 操作）")
            return

        logger.info("✅ MR操作类型符合条件，继续处理")
        
        # 仅仅在MR创建或更新时进行Code Review
        # 获取Merge Request的changes
        logger.info("🔍 开始获取MR代码变更")
        changes = handler.get_merge_request_changes()
        logger.info(f'📄 原始变更数量: {len(changes) if changes else 0}')
        
        changes = filter_changes(changes)
        logger.info(f'📄 过滤后变更数量: {len(changes) if changes else 0}')
        
        if not changes:
            logger.info('⚠️ 未检测到有关代码的修改,修改文件可能不满足SUPPORTED_EXTENSIONS。')
            return
        
        logger.info(f"✅ 检测到 {len(changes)} 个有效的代码变更")
        for change in changes[:3]:  # 只显示前3个变更的信息
            logger.info(f"  变更文件: {change.get('new_path', 'Unknown')}")

        # 获取Merge Request的commits
        logger.info("📝 开始获取MR提交信息")
        commits = handler.get_merge_request_commits()
        if not commits:
            logger.error('❌ 获取提交信息失败')
            return
        
        logger.info(f"📝 获取到 {len(commits)} 个提交")
        for i, commit in enumerate(commits[:3]):  # 只显示前3个提交的信息
            logger.info(f"  提交 {i+1}: {commit.get('title', 'No title')[:50]}...")

        # review 代码
        logger.info("🤖 开始AI代码审查")
        commits_text = ';'.join(commit['title'] for commit in commits)
        logger.info(f"📝 提交消息汇总: {commits_text[:100]}...")
        
        review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text)
        score = CodeReviewer.parse_review_score(review_text=review_result)
        logger.info(f"✅ AI审查完成，评分: {score}")

        # 将review结果提交到Gitlab的 notes
        logger.info("📤 准备将审查结果提交到GitLab MR")
        handler.add_merge_request_notes(f'Auto Review Result: \n{review_result}')
        logger.info("✅ 审查结果已提交到GitLab MR")

        # dispatch merge_request_reviewed event
        logger.info("💾 准备保存审查结果到数据库")
        event_manager['merge_request_reviewed'].send(
            MergeRequestReviewEntity(
                project_name=webhook_data['project']['name'],
                author=webhook_data['user']['username'],
                source_branch=webhook_data['object_attributes']['source_branch'],
                target_branch=webhook_data['object_attributes']['target_branch'],
                updated_at=int(datetime.now().timestamp()),
                commits=commits,
                score=score,
                url=webhook_data['object_attributes']['url'],
                review_result=review_result,
                url_slug=gitlab_url_slug,
            )
        )
        logger.info("✅ Merge Request事件处理完成，审查结果已保存")

    except Exception as e:
        error_message = f'Merge Request事件处理出现未知错误: {str(e)}\n{traceback.format_exc()}'
        logger.error(f'❌ Merge Request事件处理失败: {error_message}')
        notifier.send_notification(content=error_message)
        logger.error('🔔 错误通知已发送')

def handle_github_push_event(webhook_data: dict, github_token: str, github_url: str, github_url_slug: str):
    push_review_enabled = os.environ.get('PUSH_REVIEW_ENABLED', '0') == '1'
    try:
        handler = GithubPushHandler(webhook_data, github_token, github_url)
        logger.info('GitHub Push event received')
        commits = handler.get_push_commits()
        if not commits:
            logger.error('Failed to get commits')
            return

        review_result = None
        score = 0
        if push_review_enabled:
            # 获取PUSH的changes
            changes = handler.get_push_changes()
            logger.info('changes: %s', changes)
            changes = filter_github_changes(changes)
            if not changes:
                logger.info('未检测到PUSH代码的修改,修改文件可能不满足SUPPORTED_EXTENSIONS。')
            review_result = "关注的文件没有修改"

            if len(changes) > 0:
                commits_text = ';'.join(commit.get('message', '').strip() for commit in commits)
                review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text)
                score = CodeReviewer.parse_review_score(review_text=review_result)
            # 将review结果提交到GitHub的 notes
            handler.add_push_notes(f'Auto Review Result: \n{review_result}')

        event_manager['push_reviewed'].send(PushReviewEntity(
            project_name=webhook_data['repository']['name'],
            author=webhook_data['sender']['login'],
            branch=webhook_data['ref'].replace('refs/heads/', ''),
            updated_at=int(datetime.now().timestamp()),  # 当前时间
            commits=commits,
            score=score,
            review_result=review_result,
            url_slug=github_url_slug,
        ))

    except Exception as e:
        error_message = f'服务出现未知错误: {str(e)}\n{traceback.format_exc()}'
        notifier.send_notification(content=error_message)
        logger.error('出现未知错误: %s', error_message)


def handle_github_pull_request_event(webhook_data: dict, github_token: str, github_url: str, github_url_slug: str):
    '''
    处理GitHub Pull Request 事件
    :param webhook_data:
    :param github_token:
    :param github_url:
    :param github_url_slug:
    :return:
    '''
    try:
        # 解析Webhook数据
        handler = GithubPullRequestHandler(webhook_data, github_token, github_url)
        logger.info('GitHub Pull Request event received')

        if handler.action not in ['opened', 'synchronize']:
            logger.info(f"Pull Request Hook event, action={handler.action}, ignored.")
            return

        # 仅仅在PR创建或更新时进行Code Review
        # 获取Pull Request的changes
        changes = handler.get_pull_request_changes()
        logger.info('changes: %s', changes)
        changes = filter_github_changes(changes)
        if not changes:
            logger.info('未检测到有关代码的修改,修改文件可能不满足SUPPORTED_EXTENSIONS。')
            return

        # 获取Pull Request的commits
        commits = handler.get_pull_request_commits()
        if not commits:
            logger.error('Failed to get commits')
            return

        # review 代码
        commits_text = ';'.join(commit['title'] for commit in commits)
        review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text)

        # 将review结果提交到GitHub的 notes
        handler.add_pull_request_notes(f'Auto Review Result: \n{review_result}')

        # dispatch pull_request_reviewed event
        event_manager['merge_request_reviewed'].send(
            MergeRequestReviewEntity(
                project_name=webhook_data['repository']['name'],
                author=webhook_data['pull_request']['user']['login'],
                source_branch=webhook_data['pull_request']['head']['ref'],
                target_branch=webhook_data['pull_request']['base']['ref'],
                updated_at=int(datetime.now().timestamp()),
                commits=commits,
                score=CodeReviewer.parse_review_score(review_text=review_result),
                url=webhook_data['pull_request']['html_url'],
                review_result=review_result,
                url_slug=github_url_slug
            ))

    except Exception as e:
        error_message = f'服务出现未知错误: {str(e)}\n{traceback.format_exc()}'
        notifier.send_notification(content=error_message)
        logger.error('出现未知错误: %s', error_message)
